
// SmpTst.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"

#define DEF_SMPIO_CONSOLE		// use debugout as the default io
#define KEN_LIB_IMP
#include "SmpIO.h"
#include "SmpTst.h"
#include "stubs.h"
#include "CmdLnPars.h"

#include <iostream>

const static TCHAR* s_pszUsage=
_T("usage:\r\n")\
_T("SmpTst /option:val\r\n")\
_T("\tIO options:\r\n")\
_T("\t\t[/console(default)] [/debugout] [/file] [/input:<console|debugout|file>]\r\n")\
_T("\tTester options:\r\n")\
_T("\t\t[/list] [/result] [/test]\r\n")\
_T("\ttest options:\r\n")\
_T("\t\t\t[/cases[:case1,case2...] [/timeout:N] [/async] [/times:N] [/type[:[0(node)]|1(tree)|2(deeptree)] [/priority:N(0-255)]\r\n");


CSmpTester g_Tster;
CCmdLineParser g_CmdLnParser;


//
// default tester options
bool g_fTsterList=false;
bool g_fPirntResult=false;
bool g_fTsterTst=false;
_tstring g_strCases;
const TCHAR* g_pszTsterCases=NULL;
DWORD g_dwTsterTO=0;
bool g_fTsterAsync=false;
DWORD g_dwTsterTimes=1;
SMPTST_CASE g_enTsterType=SMPTST_CASE_NODE;
DWORD g_dwPriority=INVALID_DWORD;

VOID InitSmpIO(CCmdLineParser* pCmdLn, CSmpIO* pSmpIO)
{
	// build io
	if(pCmdLn->GetOption(_T("debugoutio")))
	{
		g_SmpIO.EnBuildInIO(TRUE, SMPIO_DBGOUT);
	}

}

VOID InitTesterVar(CCmdLineParser* pCmdLn, CSmpIO* pSmpIO)
{
	g_fTsterList=false;
	pCmdLn->GetOption(_T("list"), &g_fTsterList);

	g_fPirntResult=false;
	pCmdLn->GetOption(_T("result"), &g_fPirntResult);

	g_fTsterTst=false;
	pCmdLn->GetOption(_T("test"), &g_fTsterTst);

	g_pszTsterCases=NULL;
	g_strCases.empty();
	pCmdLn->GetOption(_T("cases"), &g_strCases);
	if(g_strCases.size())
	{
		g_pszTsterCases=g_strCases.c_str();
	}

	pCmdLn->GetOption(_T("timeout"), &g_dwTsterTO);

	pCmdLn->GetOption(_T("async"), &g_fTsterAsync);

	pCmdLn->GetOption(_T("times"), &g_dwTsterTimes);

	int type;
	if(pCmdLn->GetOption(_T("type"), &type))
	{
		if( (type<=SMPTST_CASE_DEEP_TREE) && (type>=SMPTST_CASE_NODE) )
		{
			g_enTsterType=(SMPTST_CASE)type;
		}
		else
		{
			pSmpIO->Printf(TEXT("invalide type option:%d\r\n"), type);
		}
	}

	pCmdLn->GetOption(_T("priority"), &g_dwPriority);
	if( (INVALID_DWORD!=g_dwPriority)
		&& (g_dwPriority>255) )
	{
		pSmpIO->Printf(TEXT("invalide priority:%d\r\n"), g_dwPriority);
		g_dwPriority=INVALID_DWORD;
	}
}


VOID Usage()
{
	g_SmpIO.Puts(s_pszUsage);
	g_SmpIO.IncDeep();
	g_SmpIO.IncDeep();
	g_SmpIO.Printf(_T("Test case options(/option:val):"));
	PrintCmdLnInitValName(&g_SmpIO);
	g_SmpIO.DecDeep();
	g_SmpIO.DecDeep();
}


#if (defined(WIN32) && defined(_CONSOLE))
int _tmain(int argc, const _TCHAR* argv[])
{
	// parse command options
	g_CmdLnParser.ParseArg(argc, argv);
#else
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
//	AllocConsole();

	// parse command options
	g_CmdLnParser.ParseCmdLine(lpCmdLine);
#endif
	// build up test tree
	BuildUpDefTester(&g_Tster);

	CCmdLineParser* pCmdLineParser=&g_CmdLnParser;
	bool fFirstTest=true;
	bool fLoop=false;
	TCHAR szCmdLnBuf[512];
	CCmdLineParser cInputParser;
	do
	{
		// init globale var through command line
		BuildUpCmdLnInitVal(pCmdLineParser);

		// init smpio
		InitSmpIO(pCmdLineParser, &g_SmpIO);

		// init tester related var
		InitTesterVar(pCmdLineParser, &g_SmpIO);

		pCmdLineParser->GetOption(_T("input"), &fLoop);

		//
		// list command
		if(g_fTsterList)
		{
			g_SmpIO.Printf(TEXT("<<== list test cases:%s"), g_pszTsterCases);
			g_Tster.Print(g_pszTsterCases, FALSE, &g_SmpIO);
			g_SmpIO.Puts(TEXT("Test case options(/option:val):"));
			PrintCmdLnInitValName(&g_SmpIO);
			g_SmpIO.Puts(TEXT("==>>"));
		}
		//test command
		else if(g_fTsterTst)
		{
			g_SmpIO.Printf(TEXT("<<== do test cases:%s"), g_pszTsterCases);
			// do global init
			if(fFirstTest)
			{
				fFirstTest=false;
				g_Tster.DoInitCleanFunc(TRUE, 0, &g_SmpIO);
			}

			// do test case
			for(DWORD i=0; i<g_dwTsterTimes; i++)
			{
				g_Tster.DoTest(g_pszTsterCases, g_enTsterType, !g_fTsterAsync, g_dwTsterTO, g_dwPriority, &g_SmpIO);
			}
			g_SmpIO.Puts(TEXT("==>>"));
		}
		else if(g_fPirntResult)
		{
			g_SmpIO.Puts(TEXT("<<== print test results"));
			g_SmpIO.Puts(TEXT("all result of test:"));
			g_SmpIO.IncDeep();
			g_Tster.Print(NULL, TRUE, &g_SmpIO);
			g_SmpIO.DecDeep();
			g_SmpIO.Puts(TEXT("==>>"));
		}
		else
		{
			if( ( pCmdLineParser==&g_CmdLnParser)	// the first loop
				|| (pCmdLineParser->GetOption(_T("usage"))) )
			{
				Usage();
			}
		}

		if( pCmdLineParser->GetOption(_T("exit")) )
		{
			break;
		}
		
		if(fLoop)
		{
			cInputParser.Clear();
			g_SmpIO.Puts(TEXT("\r\nPlease input options:"));
			if(0==g_SmpIO.Gets(szCmdLnBuf, ARRAYOF(szCmdLnBuf)))
			{
				break;
			}
			g_SmpIO.Puts(TEXT(""));
			cInputParser.ParseCmdLine(szCmdLnBuf);
			pCmdLineParser=&cInputParser;
		}

	}while(fLoop);

	// do global cleanup
	if(!fFirstTest)
	{
		// print all result
		g_SmpIO.Puts(TEXT("all result of test:"));
		g_SmpIO.IncDeep();
		g_Tster.Print(NULL, TRUE, &g_SmpIO);
		g_SmpIO.DecDeep();

		g_Tster.DoInitCleanFunc(FALSE, 0, &g_SmpIO);
	}

	return 0;
}
